using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Resources;
using System.Windows.Forms;
using App.Controlador;
using App.Modelo;
using App.Modelo.Interfaces;
using App.Modelo.Menu;

namespace App.Seguridad.Vista.Menu
{
    /// <summary>
    /// Clase especializada que utiliza la Controladora de seguridad 
    /// y el usuario para determinar los permisos
    /// </summary>
    public class MenuControladoraBotonera 
    {
        private ResourceManager _ResourceManager;
        private Modelo.Menu.MenuContenedor _Model;

        private Dictionary<Control, MenuBaseItem> _itemsIndex
            = new Dictionary<Control, MenuBaseItem>();

        /// <summary>
        /// El evento se lanza cuando se ejecuta un comando
        /// </summary>
        public event EventHandler<MenuEjecutarComandoEventArgs> ExecuteCommand;

        /// <summary>
        /// Retorna el manejador de recursos utilizado. Si no se establece retorna un manejador
        /// de este assembly
        /// ResourceManager se usa para encontrar las imagenes.
        /// </summary>
        public ResourceManager ResourceManager
        {
            get
            {
                if (_ResourceManager == null)
                    _ResourceManager = new ResourceManager(typeof (App.Seguridad.Vista.Properties.Resources));
                return _ResourceManager;
            }
            set { _ResourceManager = value; }
        }

        public Control.ControlCollection Controls { get; set; }
        /// <summary>
        /// Obtiene o establece el modelo de items del menu actualizando el ControlMenu
        /// </summary>
        public Modelo.Menu.MenuContenedor Model
        {
            get { return _Model; }
            set
            {
                _itemsIndex.Clear();
                _Model = value;

                Controls.Clear();

                if (_Model != null)
                {
                    foreach (var item in _Model.Items)
                    {
                        var c = createItem(item);
                        _itemsIndex[c] = item;
                        Controls.Add(c);
                    }
                    Refrescar();
                }
            }
        }

        public IDictionary<string, IComando> CatalogoComandos;

        private Button createItem(MenuBaseItem item)
        {
            var boton = new Button
                            {
                                AutoSize = true,
                                TextImageRelation = TextImageRelation.ImageAboveText,
                                TextAlign = ContentAlignment.MiddleCenter,
                                Visible = true
                            };

            if (item is MenuItemSeparator)
            {
                boton.Width = 4;
                boton.Enabled = false;
            }


            if (!String.IsNullOrEmpty(item.Image) &&
                ResourceManager.GetObject(item.Image) is Image)
            {
                boton.Image = (Image) ResourceManager.GetObject(item.Image);
            }

            boton.Text = item.Text;

            if (!String.IsNullOrEmpty(item.Command))
                boton.Click += new EventHandler(button_Click);

            return boton;
        }

        private void button_Click(object sender, EventArgs e)
        {
            if (_itemsIndex.ContainsKey((Button) sender))
            {
                MenuBaseItem item = _itemsIndex[(Button) sender];
            
                if (CatalogoComandos != null && CatalogoComandos.ContainsKey(item.Command))
                {
                    CatalogoComandos[item.Command].Ejecutar();
                }
            
                if (ExecuteCommand != null)
                    ExecuteCommand(this, new MenuEjecutarComandoEventArgs {Item = item});
            }
        }


        /// <summary>
        /// Vuelve a aplicar la seguridad
        /// </summary>
        public void Refrescar()
        {
            foreach (var it in Controls)
            {
                var element = (Button)it;
                if (element == null)
                    continue;

                if (_itemsIndex.ContainsKey(element) && _itemsIndex[element] is MenuBoton)
                {
                    var modelItem = (MenuBoton)_itemsIndex[element];
                    if (modelItem.ComprobarPermiso)
                    {
                        element.Enabled = VerificarPermiso(modelItem);
                    }
                }
            } 
        }

        Usuario _Usuario;
        IList<Perfil> _Perfiles;

        public Usuario Usuario
        {
            get
            {
                if (_Usuario == null)
                    _Usuario = ModuloSeguridad.Instance.UsuarioActual;
                return _Usuario;
            }
            set
            {
                _Usuario = value;
            }
        }

        public IList<Perfil> Perfiles
        {
            get
            {
                if (_Perfiles == null)
                    _Perfiles = ModuloSeguridad.Instance.FabricaControladoras.Factory<ControladoraPerfiles>().Get(Usuario);
                    
                return _Perfiles;
            }
        }

        public MenuControladoraBotonera()
        {
            // me registro al evento UsuarioModificado para actualizar el menu
            ControladoraUsuarios.UsuarioModificado
                += Seguridad_UsuarioModificado;

            // me registro al evento GrupoModificado para actualizar el menu

            ControladoraGrupos.GrupoModificado
                += Grupos_GrupoModificado;
        }


        void Grupos_GrupoModificado(object sender, GrupoEventArgs e)
        {
            // blanqueo la propiedad para que se vuelva a consultar a la controladora
            _Perfiles = null;

            // is el grupo modificado es el grupo del usuario 
            
            if (Usuario.Grupos.Any(gr => gr.Equals(e.Grupo)))
            {
                Refrescar();
            }
        }

        void Seguridad_UsuarioModificado(object sender, UsuarioEventArgs e)
        {
            // blanqueo la propiedad para que se vuelva a consultar a la controladora
            _Perfiles = null;

            // si es el usuario actual
            if (e.Usuario.Equals(Usuario))
            {
                Refrescar();
            }
        }

        /// <summary>
        /// Implementacion del metodo VerificarPermiso que comprueba si el usuario tiene permiso a una determinada accion
        /// consultando a la controladora de seguridad
        /// </summary>
        /// <param name="boton"></param>
        /// <returns></returns>
        public bool VerificarPermiso(MenuBoton boton)
        {
            if (String.IsNullOrEmpty(boton.Command))
                return true;

            var perfil = ControladoraPerfiles.ParsePerfil(boton.Command);

            if (perfil.Formulario == null || perfil.Funcion == null)
                return true;

            foreach (Perfil p in Perfiles)
                if (p.Coincide(perfil))
                    return true;
            return false;
        }

        private ControladoraPerfiles _ControladoraPerfiles;
        public ControladoraPerfiles ControladoraPerfiles
        {  
            get
            {
                if (null == _ControladoraPerfiles)
                    _ControladoraPerfiles =
                        ModuloSeguridad.Instance.FabricaControladoras.Factory<ControladoraPerfiles>();
                return _ControladoraPerfiles;
            }
            set
            {
                _ControladoraPerfiles = value;
            }
        }


    }
}